package com.xcity.util;

import java.util.concurrent.atomic.AtomicInteger;

import com.xcity.db.entity.Config;
import com.xcity.db.mapper.ConfigMapper;

import naga.x.App;

/**
 * id生成器<br/>
 * 规则:<br/>
 *   (serverId << 35) | (type << 31) | id 
 * @author yang.li
 *
 */
public class IdUtils {
	
	static enum IdType {
		TEMP(0, Config.KEY_TEMP_ID), // 临时id,转为其他id后则浪费
		ACCOUNT(1, Config.KEY_ACC_NUM),
		PLAYER(2, Config.KEY_PLAYER_NUM),
		ITEM(3, Config.KEY_ITEM_NUM),
		PET(4, Config.KEY_PET_NUM),
		EMPLOYEE(5, Config.KEY_EMPLOYEE_NUM),
		EQUIPMENT(6, Config.KEY_EQUIPMENT_NUM),
		GUILD(7, Config.KEY_GUILD_NUM);
		int type;
		String key;
		AtomicInteger generator;
		IdType(int type, String key) {
			this.type = type;
			this.key = key;
		}
	}
	
	public static int serverId;
	
	static {
//		serverId = App.getApp().getConfig().getIntValue(naga.x.common.Config.SERVER_ID);
		serverId = App.getApp().getConfig().serverId;
		IdType[] vals = IdType.values();
		for (IdType val : vals) {
			Config cfg = DBUtils.find(val.key, ConfigMapper.class);
			if (cfg == null) {
				DBUtils.save(cfg = new Config(val.key, 0), ConfigMapper.class);
			}
			val.generator = new AtomicInteger(cfg.getIntValue());
		}
	}
	
	public static void init() {
	}
	
	/**
	 * must be invoke when server shutdown
	 */
	public static void close() {
		IdType[] vals = IdType.values();
		for (IdType val : vals) {
			DBUtils.update(new Config(val.key, String.valueOf(val.generator.get())), ConfigMapper.class);
		}
	}
	
	public static long nextAccountId() {
		return nextId(IdType.ACCOUNT);
	}
	
	public static long nextPlayerId() {
		return nextId(IdType.PLAYER);
	}
	
	public static long nextItemId() {
		return nextId(IdType.ITEM);
	}
	
	public static long nextPetId() {
		return nextId(IdType.PET);
	}
	
	public static long nextEmployeeId() {
		return nextId(IdType.EMPLOYEE);
	}
	
	public static long nextEquipmentId() {
		return nextId(IdType.EQUIPMENT);
	}
	
	public static long nextTempId() {
		return nextId(IdType.TEMP);
	}
	
	public static long nextGuildId(){
		return nextId(IdType.GUILD);
	}
	
	public static int sizeOfAccount() {
		return size(IdType.ACCOUNT);
	}
	
	public static int sizeOfPlayer() {
		return size(IdType.PLAYER);
	}
	
	public static int sizeOfItem() {
		return size(IdType.ITEM);
	}
	
	public static long firstIdOfAccount() {
		return firstIdOf(IdType.ACCOUNT);
	}
	
	public static long firstIdOfPlayer() {
		return firstIdOf(IdType.PLAYER);
	}
	
	public static long firstIdOfItem() {
		return firstIdOf(IdType.ITEM);
	}
	
	public static long firstIdOfGuild(){
		return firstIdOf(IdType.GUILD);
	}
	
	static long firstIdOf(IdType idType) {
		return ((long) serverId << 35) | ((long) idType.type << 31) | 1;
	}
	
	static int size(IdType idType) {
		return idType.generator.get();
	}
	
	static long nextId(IdType idType) {
		return ((long) serverId << 35) | ((long) idType.type << 31) | idType.generator.incrementAndGet();
	}
	
}
